﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DataModel
{
    public class ContentType : IComparable
    {
        private String id;
        private String name;
        private String notes;
        private List<SiteColumn> scList;
        private ContentType parent;
        private String group;
        private Boolean isApproved;

        public String ID { get { return id; } set { } }
        public String Name { get { return name; } set { name = value; } }
        public String Notes { get { return notes; } set { notes = value; } }
        public List<SiteColumn> SCList { get { return scList; } set { } }
        /// <summary>
        /// Gets the inherited sc list.
        /// </summary>
        /// <value>
        /// The inherited sc list.
        /// </value>
        public List<SiteColumn> InheritedSCList
        {
            get
            {
                List<SiteColumn> inheritedSCs = new List<SiteColumn>();
                if (this.parent != null && this != this.parent)
                {
                    foreach (SiteColumn sc in this.parent.scList)
                    {
                        if (!inheritedSCs.Contains(sc))
                        {
                            inheritedSCs.Add(sc);
                        }
                    }

                    foreach (SiteColumn sc in this.parent.InheritedSCList)
                    {
                        if (!inheritedSCs.Contains(sc))
                        {
                            inheritedSCs.Add(sc);
                        }
                    }
                }
                /*
                while (true)
                {
                    ContentType i = this.Parent;
                    try
                    {
                        inheritedSCs.AddRange(i.scList);
                        i = i.Parent;
                        if (i == i.Parent || i == null) { break; }
                    }
                    catch
                    {
                        break;
                    }
                }
                 * */
                return inheritedSCs;
            }
        }
        /// <summary>
        /// Gets or sets the parent, and sets ParentIsFromDump to true if the parent was from SPDump_ContentTypes
        /// </summary>
        /// <value>
        /// The parent.
        /// </value>
        public ContentType Parent { get { return parent; } set { 
            parent = value;
            if (SaveFile.SPDump_contentTypes.Count(ct => ct.Name == parent.Name) > 0)
            {
                ParentIsFromDump = true;
            }
            else
            {
                ParentIsFromDump = false;
            }
        } }
        public String Group { get { return group; } set { group = value; } }
        public Boolean IsApproved { get { return isApproved; } set { isApproved = value; } }
        public Boolean ParentIsFromDump { get; set; }

        public static ContentType ROOT_TYPE = new ContentType();

        /// <summary>
        /// Checks the name to see if it's valid in SharePoint.
        /// </summary>
        /// <param name="n">The name.</param>
        /// <returns>The first invalid character found, if any.</returns>
        public static string ValidName(String n)
        {
            foreach (String s in "\\  / : * ? \" # % < > { } | ~ & .. \t".Split(new char[] { ' ' }))
            {
                if (n.Contains(s) || n.EndsWith("."))
                {
                    return s;
                }
            }
            return "";
        }

        private ContentType() //this ensures this only gets called when creating the ROOT_TYPE 
        {
            this.id = "guid goes here";
            this.name = "Item";
            this.notes = "System root content type";
            this.scList = new List<SiteColumn>();
            this.parent = this;
            this.group = "System";
            this.isApproved = true;
        }

        public ContentType(String id, String name, String desc, List<SiteColumn> scList, ContentType parent, String group = "Custom Content Types", bool isApproved = false)
        {
            this.id = id;
            this.name = name;
            this.notes = desc;
            this.scList = scList;
            this.group = group;
            this.parent = parent;
            this.isApproved = isApproved;
        }

        public ContentType(String name)
        {
            id = GUID.get();
            this.name = name;
            notes = "";
            scList = new List<SiteColumn>();
            this.parent = ContentType.ROOT_TYPE;
            group = "Custom Content Types";
            isApproved = false;
        }

        /// <summary>
        /// Determines whether this is a descendant of the specified ct.
        /// </summary>
        /// <param name="ct">The ct.</param>
        /// <returns>Whether or not this is a descendant of the specified ct</returns>
        public Boolean IsDescendantOf(ContentType ct)
        {
            ContentType i = this.Parent;
            while (true)
            {
                try
                {
                    if (i == ct) { return true; }
                    i = i.Parent;
                    if (i == i.Parent) { break; }
                }
                catch
                {
                    break;
                }
            }
            return false;
        }

        int IComparable.CompareTo(object obj)
        {
            ContentType ct = (ContentType)obj;
            return String.Compare(this.Name, ct.Name);
        }

        /// <summary>
        /// An ICOmparer that sorts the inheritance descending.
        /// </summary>
        /// <returns></returns>
        public static IComparer<ContentType> sortInheritanceDescending()
        {
            return (IComparer<ContentType>)new myComparer();
        }

        private class myComparer : IComparer<ContentType>
        {
            public int Compare(ContentType ctX, ContentType ctY)
            {
                if (ctX.IsDescendantOf(ctY))
                {
                    return 1;
                }
                else if (ctY.IsDescendantOf(ctX))
                {
                    return -1;
                }
                else
                {
                    return 0;
                }
            }
        }
    }
}
